%{
#include <cstring>
#include <cmath>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <iomanip>
using std::setw;
using std::setprecision;

#define 		MENOR		1
#define 		MENIG		2
#define			MAIOR   	3
#define			MAIG		4
#define			IGUAL		5
#define			DIFER		6
#define			MAIS		1
#define			MENOS		2
#define			VEZES		1
#define			DIV		2
#define			RESTO		3
#define			AND		1
#define			NAO		2
#define			OU		3

/*
enum { BOOLEANO=14, CARACTERE, CHAMAR, COMANDOS, ENQUANTO, ENTAO, ESCREVER, FALSO, FAZER, GLOBAIS, INTEIRO, LER, LOCAIS, NENHUM, PARA, PRINCIPAL, PROGRAMA,
       PROTOTIPOS, REAL, RETORNAR, SE, SENAO, VERDADE, OU, AND, NAO, ABPAR, FPAR, ABCOL, FCOL, ABCHAV, FCHAV, ABTRIP, FTRIP, PVIRG, VIRG, DPONTS, ATRIB,
       CTCHAR, INVAL };
*/

//Prototypes to keep the compiler and baggio happy :-)
void yyerror (const char *error);
int yyparse();
int  yylex ();
void tabular();


%}
delim			[ \t\n\r]
ws			{delim}+
digito			[0-9]
letra			[A-Za-z]
ctint			{digito}+
id			[_]*{letra}({letra}|{digito}|[_])*
real 			{digito}+\.{digito}*([eE][+-]?{digito}+)?
carac1			\\.|[^\\']
caractere 		'{carac1}'
carac2			\\.|[^\\\"]
cadeia 			\"{carac2}*\"
comentario		\/\*[^(\*\/)]*\*\/
%%
{ws}		{ ;}
{comentario}	{ ;}
booleano	{ return BOOLEANO;}
carac		{ return CARACTERE;}
chamar		{ return CHAMAR;}
comandos	{ return COMANDOS;}
enquanto	{ return ENQUANTO;}
entao 		{ return ENTAO;}
escrever	{ return ESCREVER;}
falso		{ return FALSO;}
fazer		{ return FAZER;}
globais		{ return GLOBAIS;}
int		{ return INTEIRO;}
ler		{ return LER;}
locais		{ return LOCAIS;}
nenhum		{ return NENHUM;}
para		{ return PARA;}
principal	{ return PRINCIPAL;}
programa	{ return PROGRAMA;}
prototipos	{ return PROTOTIPOS;}
real		{ return REAL;}
retornar	{ return RETORNAR;}
se		{ return SE;}
senao		{ return SENAO;}
verdade		{ return VERDADE;}
{id}		{strcpy (yylval.cadeia, yytext); return ID;}
{ctint}		{yylval.valor = atoi(yytext); return CTINT;}
{real}		{yylval.num = atof(yytext); return CTREAL;}
{caractere}	{strcpy (yylval.cadeia, tratachar( yytext ) ); return CTCHAR;}
{cadeia}	{strcpy (yylval.cadeia, yytext); tratacadeia(yylval.cadeia); return CADEIA;}
"<"		{yylval.atr = MENOR; return OPREL;}
"<="		{yylval.atr = MENIG; return OPREL;}
">"		{yylval.atr = MAIOR; return OPREL;}
">="		{yylval.atr = MAIG; return OPREL;}
"="		{yylval.atr = IGUAL; return OPREL;}
"!="		{yylval.atr = DIFER; return OPREL;}
"||"		{yylval.atr = OU; return OPOR;}
"&&"		{yylval.atr = AND; return OPAND;}
"!"		{yylval.atr = NAO; return OPNOT;}
"+"		{yylval.atr = MAIS; return OPAD;}
"-"		{yylval.atr = MENOS; return OPAD;}
"*"		{yylval.atr = VEZES; return OPMULT;}
"/"		{yylval.atr = DIV; return OPMULT;}
"%"		{yylval.atr = RESTO; return OPMULT;}
"~"		{strcpy (yylval.cadeia, yytext); return OPNEG;}
"("		{ return ABPAR;}
")"		{ return FPAR;}
"["		{ return ABCOL;}
"]"		{ return FCOL;}
"{{{"		{ return ABTRIP;}
"}}}"		{ return FTRIP;}
"{"		{ return ABCHAV;}
"}"		{ return FCHAV;}
";"		{ return PVIRG;}
","		{ return VIRG;}
":"		{ return DPONTS;}
"<-"		{ return ATRIB;}
.		{yylval.mander = yytext[0]; return INVAL;}
%%

char tratachar (char *s) {
	if (s[1] != '\\')
		return s[1];
	else
		switch (s[2]) {
			case 'a': 	return 7;
			case '\\': 	return 92;
			case 'b': 	return 8;
			case 'r': 	return 13;
			case '\"': 	return 34;
			case 'f': 	return 12;
			case 't': 	return 9;
			case 'n': 	return 10;
			case '\0': 	return 0;
			case '\'': 	return 39;
			case 'v': 	return 11;
         		default:	return s[2];
		}
}
void tratacadeia (char *s) {
	int i, n, d;
	n = strlen (s);
	for (i = 0, d = 1; i <= n-2-d; i++)   {
		if (s[i+d] != '\\')
			s[i] = s[i+d];
		else {
			switch (s[i+d+1]) {
				case 'a': 	s[i] = 7;break;
				case '\\': 	s[i] = 92; break;
				case 'b': 	s[i] = 8; break;
				case 'r': 	s[i] = 13; break;
				case '\"': 	s[i] = 34; break;
				case 'f': 	s[i] = 12; break;
				case 't': 	s[i] = 9;  break;
				case 'n': 	s[i] = 10; break;
				case '\0': 	s[i] = 0;  break;
				case '\'': 	s[i] = 39; break;
				case 'v': 	s[i] = 11; break;
				default:	s[i] = s[i+d+1];
			}
			d++;
		}
	}
	s[i] = s[n];
}


//FALTA FAZER TRATAMENTO DE COMENTÁRIOS E ARRUMAR A MAIN
/*
main () {
	int i;
	cout << "\n       texto       |   tipo   |      atributo \n";
	cout << "--------------------------------------------------------------\n";
	while (i = yylex ()) {
		cout << setw( 20 ) << yytext << setw( 10 ) << i;
		switch (i) {
			case ID:
			case CTCHAR:
			case CADEIA:
				cout << setw( 20 ) << yylval.cadeia; break;
			case CTINT:
				cout << setw( 20 ) << yylval.valor; break;
			case OPOR:
			case OPAND:
			case OPNOT:
			case OPAD:
			case OPMULT:
			case OPNEG:
			case OPREL:
				cout << setw( 20 ) << yylval.atr; break;
			case INVAL: 
				cout << setw( 20 ) << yylval.mander; break;
			case CTREAL:
				cout << setw( 20 ) << setprecision( 3 ) << yylval.num; break;
			default:
				break;

		}
        cout << endl;
	}
}
*/
